package Game;
import java.io.Serializable;
import java.util.ArrayList;

/**
 * Caravan.java
 * 
 * This class represents the caravan object. In the game, the caravan is the collection of all the players, their vehicles, and their inventory.
 * 
 * @author Ray DeCuir
 * @version 1.2
 *
 */

public class Caravan implements Serializable{
	
	// the player's inventory
	private Inventory playerInventory; 
	
	// The current location of the player
	private GPS playerGPS; 
	
	// characters in the player's caravan
	private ArrayList<Character> playerCharacters; 
	
	// vehicles in the player's caravan
	private ArrayList<Vehicle> playerVehicles; 
	
	// the playyer's money and number of day
	private int playerMoney, daysPast; 
	
	/**
	 * Constructor for the Caravan object. It creates the arrayLists for the characters and vehicles, then creates the character's based on the information 
	 * given in the configuration screens. 
	 * 
	 * @param startingCity The starting location of the player
	 */
	public Caravan(int startingCity)
	{
		playerMoney = 0;
		daysPast = 0;
		playerInventory = new Inventory();
		playerCharacters = new ArrayList<Character>();
		playerVehicles = new ArrayList<Vehicle>();
		playerGPS = new GPS(startingCity);
		Party[] party = Party.values();
		
		// Create the player characters based on the information given in the configuration screens
		for ( Party partyMember : party )
		{
			if ( partyMember.getName() != null ) 
			{
				playerCharacters.add( new Character( partyMember.getName(), partyMember.getProfession() ));
				System.out.println("New character named " + partyMember.getName() + " with profession " + partyMember.getProfession() + " added.");
				playerMoney += partyMember.getProfession().getStartingMoney();
			}
		}
	} 
	
	/**
	 * Setter for the player money
	 * 
	 * @param playerMoney The new player money
	 */
	public void setPlayerMoney( int playerMoney)
	{
		this.playerMoney = playerMoney;
	}
	
	/**
	 * Setter for player inventory
	 * @param playerInventory
	 */
	public void setPlayerInventory(Inventory playerInventory) {
		this.playerInventory = playerInventory;
	}
	
	public void addVehicle(Vehicle v) {
		playerVehicles.add(v);
	}
	/**
	 * Gets the player's current money
	 * 
	 * @return The player's current money
	 */
	public int getPlayerMoney()
	{
		return playerMoney;
	}
	
	/**
	 * Rebuilds the player list based on party.
	 */
	public void refreshCharacters() {
		Party[] party = Party.values();
		playerCharacters.clear();
		// Create the player characters based on the information given in the configuration screens
		for ( Party partyMember : party )
		{
			if ( partyMember.getName() != null ) 
			{
				playerCharacters.add( new Character( partyMember.getName(), partyMember.getProfession() ));
			}
		}
	}
	
	/**
	 * 
	 * Get's the caravan gps object
	 * 
	 * @return The caravan gps object
	 */
	public GPS getCaravanGPS() {
		return playerGPS;
	}
	
	/**
	 * 
	 * Set's the caravan gps object
	 * 
	 * @param The caravan gps object
	 */
	public void setCaravanGPS(GPS gps) {
		playerGPS = gps;
	}
	
	
	/**
	 * Get's the player's inventory
	 * 
	 * @return The player's inventory object
	 */
	public Inventory getPlayerInventory() {
		return playerInventory;
	}
	
	
	/**
	 * 
	 * Gets the characters in the player's caravan
	 * 
	 * @return The player's characters in the caravan
	 */
	public ArrayList<Character> getCharacters() {
		return playerCharacters;
	}
	
	/**
	 * 
	 * Gets the vehicles in the player's caravan
	 * 
	 * @return The player's vehicles in the caravan
	 */
	public ArrayList<Vehicle> getVehicles() {
		return playerVehicles;
	}
	
	
	
	/**
	 * Get max weight limit of all vehicles
	 * 
	 * @return Max weight limit
	 */
	public int getTotalWeightLimit() {
		int totalWeight = 0;
		for (Vehicle curVehicle : playerVehicles)
			totalWeight += curVehicle.getWeightCapacity();
		return totalWeight;
	}

	/**
	 * This is going to be pretty much the "take turn" method
	 * It should provide rations, move the vehicle ect... 
	 */
	public void increaseDay() {
		// TODO Auto-generated method stub
		daysPast ++;
	}
	
	public int getDaysPast() {
		return daysPast;
	}
	
	/**
	 * This method calls the feed method on each character in the list based on the ration chosen and food remaining
	 * 
	 * @param playerRation The ration level to feed all of the characters
	 */
	public void feedCharacters(Ration playerRation)
	{
		double amount = 0;
		for ( Character ch : playerCharacters )
		{
			amount += ch.getProfession().getConsumptionMulti() * Ration.getConsumptionLevel() * playerRation.getMulti();
		}
		if ( amount >= playerInventory.getRemainingFood() )
		{
			playerInventory.decreaseFood(playerInventory.getRemainingFood());
			amount = (int)(Math.ceil(amount / playerCharacters.size()));
			for ( Character ch : playerCharacters)
			{
				ch.feed((int)amount);
			}
		}
		else
		{
			playerInventory.decreaseFood((int)(Math.ceil(amount)));
			for ( Character ch : playerCharacters)
			{
				amount = (int)(Math.ceil(ch.getProfession().getConsumptionMulti() * Ration.getConsumptionLevel() * playerRation.getMulti()));
				ch.feed((int)amount);
			}
		}
	}
	
	/**
	 * Updates all of the Donkey's and characters that a player has based on the pace 
	 * selected for that turn
	 * 
	 * @param playerPace The pace set by the player for the turn
	 */
	public void travelUpdate(Pace playerPace)
	{
		for ( Character ch : playerCharacters)
		{
			ch.travelUpdate(playerPace);
		}
		for ( Vehicle vh : playerVehicles)
		{
			if ( vh.getDonkey() != null)
				vh.getDonkey().travelUpdate( playerPace);
		}
	}
	
	/**
	 * Gets the number of live characters with a given profession
	 * 
	 * @param type The Character profession
	 * @return The number of characters with that profession
	 */
	public int countCharacterType(CharacterType type)
	{
		int  count = 0;
		for ( Character c : playerCharacters)
		{
			if ( c.getProfession().equals(type ) && c.isAlive()){
				count++;
			}
		}
		return count;
	}
	
	/**
	 * Gets and returns a randomly selected member of the player's caravan
	 * 
	 * @return A randomly selected member of the player's caravan
	 */
	public Character getRandomCharacter()
	{
		ArrayList<Character> c = new ArrayList<Character>();
		for ( Character ch : playerCharacters)
		{
			if ( ch.isAlive() )
			{
				c.add(ch);
			}
		}
		if ( c.size() > 0)
			return playerCharacters.get((int)(Math.random()*c.size()));
		else
			return null;
	}
	
	
	


}
